package com.sleepapp.handle;

import cn.dev33.satoken.exception.NotLoginException;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.sleepapp.dto.exception.CustomizeException;
import com.sleepapp.utils.ResCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * @author ziluxike
 * @since 2025/5/26 14:14
 */
@ControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
    /**
     * 自定义异常类
     */
    @ExceptionHandler(CustomizeException.class)
    public void myException(CustomizeException customizeException, HttpServletResponse response) throws IOException {
        if (response == null) {
            return;
        }
        response.setContentType("application/json;charset=UTF-8");
        response.setStatus(HttpServletResponse.SC_OK);
        Map<String, Object> res = new HashMap<>(2);
        res.put("code", customizeException.getCode());
        res.put("message", customizeException.getMsg());
        response.getWriter().write(JSONObject.toJSONString(res));
    }

    @ExceptionHandler({NotLoginException.class})
    public void notLoginException(HttpServletResponse response,
                                  HttpServletRequest request,
                                  NotLoginException e) throws IOException {

        response.setContentType("application/json;charset=UTF-8");
        response.setStatus(HttpServletResponse.SC_OK);
        Map<String, Object> res = new HashMap<>(3);
        res.put("code", ResCode.UNAUTHORIZED);
        String type = e.getType();
        String message;

        // -2 会话无效 -3 会话已过期 -4 您的账号已在其他地方登录 -5 您已被管理员强制下线 -6 您已被冻结 默认 当前会话未登录
        switch (type) {
            case "-2":
                message = "当前会话无效";
                break;
            case "-3":
                message = "当前会话已过期";
                break;
            case "-4":
                message = "您的账号已在其他地方登录";
                break;
            case "-5":
                message = "您已被管理员强制下线";
                break;
            case "-6":
                message = "您已被冻结";
                break;
            default:
                message = "当前会话未登录";

        }

        res.put("message", message);
        response.getWriter().write(JSONObject.toJSONString(res));
    }


    /**
     * 表单绑定到 java bean 出错时抛出 BindException 异常
     *
     * @param e
     * @return
     */
    @ExceptionHandler({BindException.class})
    protected void bindException(BindException e, HttpServletRequest request, HttpServletResponse response) throws IOException {
        response.setContentType("application/json;charset=UTF-8");
        response.setStatus(HttpServletResponse.SC_OK);
        Map<String, Object> res = new HashMap<>(3);
        res.put("code", ResCode.REQUEST_PARAM_ERROR.getCode());
        if (e.getBindingResult().hasErrors()) {
            FieldError fieldError = e.getBindingResult().getFieldError();
            if (fieldError != null) {
                // 自定义错误信息
                String message = "请检查格式!";
                if (StrUtil.isNotBlank(fieldError.getDefaultMessage()) && fieldError.getDefaultMessage().length() < 10) {
                    message = fieldError.getDefaultMessage();
                }
                res.put("message", String.format("字段 [%s] 的值无效：%s",
                        fieldError.getField(),
                        message));
            } else {
                // 如果没有字段错误，提供通用错误消息
                res.put("message", ResCode.REQUEST_PARAM_ERROR.getMessage());
            }
        } else {
            // 如果没有任何错误，提供统一的错误消息
            res.put("message", ResCode.REQUEST_PARAM_ERROR.getMessage());
        }
        response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
        response.getWriter().write(JSONObject.toJSONString(res));
    }
}
